package ve.gob.cne.action.reportes;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletContext;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JExcelApiExporter;
import net.sf.jasperreports.engine.export.JExcelApiExporterParameter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.fill.JRFileVirtualizer;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import ve.gob.cne.action.common.SaceCommonAction;
import ve.gob.cne.to.CompuestoTo;
import ve.gob.cne.to.ExtintorTo;
import ve.gob.cne.to.HistoricoTo;
import ve.gob.cne.to.TipoFuegoTo;
import ve.gob.cne.util.ApplicationProperties;
import ve.gob.cne.util.DateUtil;
import ve.gob.cne.util.enums.TipoDocumento;
import ve.gob.cne.util.enums.TipoOrientacion;

public class ReporteAction extends SaceCommonAction {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6750920140185019143L;
	private final static Logger logger = Logger.getLogger(ReporteAction.class);

	private String contentType;
	private String fileName;
	private String tipoReporte;
	private String extensionReporte;
	private InputStream inputStream;
	private HashMap<String, Object> parameters = null;
	/* atributo para saber cual reporte generar, pdf o xls */
	private TipoOrientacion tipoOrientacion;
	/** atributo para almacenar el tipo de documento del reporte */
	private TipoDocumento tipoDocumento;
	private List<ExtintorTo> listaExtintores;
	private List<String> codes;
	private String code;
	private ExtintorTo extintor;
	private String responsable;
	private Date finUltimoMantenimiento;
	private Date inicioUltimoMantenimiento;
	private Date finProximoMantenimiento;
	private Date inicioProximoMantenimiento;

	@SuppressWarnings("unchecked")
	public String init() {
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		DateFormat format = sdf;

		try {

			listaExtintores = this.getServicioExtintor().getExtintores();
			List<ExtintorTo> temp = new ArrayList<ExtintorTo>();
			for (ExtintorTo e : listaExtintores) {
				if (e.getHabilitado() != 0) {
					e.setAlerta(DateUtil.getDateDiff(1,
							e.getUltimoMantenimiento(), new Date()) > 11 ? true
							: false);
					e.setUltimoMantenimiento(format.parse(sdf.format(e
							.getUltimoMantenimiento())));
					e.setProximoMantenimiento(format.parse(sdf.format(e
							.getProximoMantenimiento())));
					temp.add(e);

				}
				listaExtintores = new ArrayList<ExtintorTo>();
				listaExtintores = temp;
			}
			if (listaExtintores != null && listaExtintores.size() != 0) {
				this.codes = new ArrayList<String>();
				for (int i = 0; i < listaExtintores.size(); i++) {
					codes.add(listaExtintores.get(i).getCodigo());
				}
				this.getSession().put("codes", codes);
				this.getSession().put("listaExtintores", listaExtintores);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return SUCCESS;
	}

	@SuppressWarnings("unchecked")
	public String consult() {

		List<ExtintorTo> extintores = (List<ExtintorTo>) this.getSession().get(
				"listaExtintores");
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		DateFormat format = sdf;
		try {

			if (extintores != null && !extintores.isEmpty()) {
				for (ExtintorTo e : extintores) {
					if (e.getCodigo().equalsIgnoreCase(this.getCode())) {
						e.setTipofuegos(this.getServicioExtintor()
								.getTipoFuegosByIdExtintor(e.getId()));
						extintor = e;
						extintor.setUltimoMantenimiento(format.parse(sdf
								.format(extintor.getUltimoMantenimiento())));
						extintor.setProximoMantenimiento(format.parse(sdf
								.format(extintor.getProximoMantenimiento())));
						extintor.setAlerta(DateUtil.getDateDiff(1,
								extintor.getUltimoMantenimiento(), new Date()) > 11 ? true
								: false);
						this.getSession().put("extintor", extintor);
						extintor = null;
					}
				}
			}
		} catch (Exception e) {
			logger.error("Ha ocurrido un error con el siguiente mensaje: " + e);
		}
		return SUCCESS;
	}

	@SuppressWarnings("unchecked")
	public String generarReporte() {
		clearErrorsAndMessages();

		JRBeanCollectionDataSource dataSource;
		ServletContext context = ServletActionContext.getServletContext();
		String filetemp = File.separator.concat(ApplicationProperties
				.getProperty("dir.filetemp"));
		filetemp = filetemp.concat(File.separator).concat(
				ApplicationProperties.getProperty("dir.filetemp.reportes"));
		JRFileVirtualizer fileVirtualizer = new JRFileVirtualizer(5,
				context.getRealPath(filetemp));
		Collection<Object> listaDatosReporte = null;
		JasperPrint jasperPrint = null;
		String nombreArchivoReporte;

		try {
			obtenerContents();
			tipoOrientacion = TipoOrientacion.HORIZONTAL;

			listaDatosReporte = (Collection<Object>) parameters
					.get("LISTA_DATOS_REPORTES");
			dataSource = new JRBeanCollectionDataSource(listaDatosReporte);

			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			fileName = (String) parameters.get("REPORT_NAME");
			nombreArchivoReporte = context
					.getRealPath("/resources/reportes/compilados/".concat(
							fileName).concat(".jasper"));
			fileName = fileName.concat(extensionReporte);
			jasperPrint = JasperFillManager.fillReport(nombreArchivoReporte,
					parameters, dataSource);

			switch (tipoDocumento) {
			case PDF:
				JRPdfExporter pdfExporter = new JRPdfExporter();
				pdfExporter.setParameter(JRExporterParameter.JASPER_PRINT,
						jasperPrint);
				pdfExporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
						byteArrayOutputStream);
				pdfExporter.exportReport();
				break;

			case EXCEL:
				JExcelApiExporter xlsExporter = new JExcelApiExporter();
				xlsExporter.setParameter(JRExporterParameter.JASPER_PRINT,
						jasperPrint);
				xlsExporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
						byteArrayOutputStream);
				xlsExporter.setParameter(
						JExcelApiExporterParameter.IS_DETECT_CELL_TYPE,
						Boolean.TRUE);
				xlsExporter.setParameter(
						JExcelApiExporterParameter.IS_WHITE_PAGE_BACKGROUND,
						Boolean.FALSE);
				xlsExporter
						.setParameter(
								JExcelApiExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_COLUMNS,
								Boolean.TRUE);
				xlsExporter
						.setParameter(
								JExcelApiExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
								Boolean.TRUE);
				xlsExporter.exportReport();
				break;

			case HTML:
				JRHtmlExporter htmlExporter = new JRHtmlExporter();
				htmlExporter.setParameter(JRExporterParameter.JASPER_PRINT,
						jasperPrint);
				htmlExporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
						byteArrayOutputStream);
				htmlExporter.exportReport();
				break;

			default:
				break;
			}

			parameters.put(JRParameter.REPORT_VIRTUALIZER, fileVirtualizer);
			parameters.put("TIPO_DOCUMENTO", tipoDocumento.ordinal());

			inputStream = new ByteArrayInputStream(
					byteArrayOutputStream.toByteArray());

			return "sendFile";
		} catch (JRException e) {
			logger.error(e);

		} catch (Exception ex) {
			logger.error(ex);

		} finally {

			listaDatosReporte = null;
			jasperPrint = null;
			fileVirtualizer.cleanup();
			try {

			} catch (Exception e) {
				logger.warn(" No se pudo cerrar la conexion", e);
			}

		}

		return INPUT;
	}

	public String generarReporteHistoricoExtintor() {
		ExtintorTo extintor = (ExtintorTo) this.getSession().get("extintor");
		parameters = new HashMap<String, Object>();
		List<HistoricoTo> historial = null;
		List<HistoricoTo> lista = new ArrayList<HistoricoTo>();
		try {

			historial = this.getServicioHistorico().getHistorico(
					extintor.getId());
			for (HistoricoTo h : historial) {
				h.setNombreOperacion(h.getOperacion().name());
				lista.add(h);
			}
			parameters.put("REPORT_NAME", "HistoricoPorExtintor");
			parameters.put("LISTA_DATOS_REPORTES", lista);

		} catch (Exception e) {
			logger.error("Ha ocurrido un error inesperado " + e);
		}
		return this.generarReporte();
	}

	public String generarPlanilla() {
		ExtintorTo extintor = (ExtintorTo) this.getSession().get("extintor");
		parameters = new HashMap<String, Object>();
		StringBuffer temp = new StringBuffer();

		try {
			ExtintorTo result = this.getServicioExtintor().getExtintor(
					extintor.getId());
			parameters.put("REPORT_NAME", "PlanillaInspeccion");
			parameters.put("REPORT_TITLE", "Planilla para Inspección");
			parameters.put("CODIGO", result.getCodigo());
			parameters.put("MODELO", result.getModelo().getDescripcion());
			parameters.put("PESO", String.valueOf(result.getPeso().getPeso()));
			parameters.put("ULTIMO_MANTENIMIENTO", result
					.getUltimoMantenimiento().toString());
			parameters.put("NOMBRES", result.getResponsable().getNombres());
			parameters.put("APELLIDOS", result.getResponsable().getApellidos());
			parameters.put("CARGO", result.getResponsable().getCargo()
					.getDescripcion());
			parameters.put("EMAIL", result.getResponsable().getCorreo());
			parameters.put("COMPUESTO", result.getCompuesto().getDescripcion());
			parameters.put("UBICACION_ADMINISTRATIVA", result
					.getUbicacionAdministrativa().getDescripcion());
			parameters.put("SEDE", result.getSede().getDescripcion());
			parameters.put("AREA", result.getArea());
			parameters.put("TELEFONO", result.getResponsable().getTelefono());
			parameters.put("PROXIMO_MANTENIMIENTO", result
					.getProximoMantenimiento().toString());
			for (TipoFuegoTo tf : result.getTipofuegos()) {
				temp.append(tf.getDescripcion());
				temp.append(", ");
			}
			parameters.put("TIPO_FUEGO", temp.toString());
			parameters.put("TIPO_UBICACION", result.getUbicacion()
					.getDescripcion());
			parameters.put("CEDULA",
					String.valueOf(result.getResponsable().getCedula()));
			parameters.put("LISTA_DATOS_REPORTES", new ArrayList<Object>());

		} catch (Exception e) {
			logger.error("Ha ocurrido un error inesperado " + e);
		}
		return this.generarReporte();
	}

	public String generarReporteGeneral() {

		parameters = new HashMap<String, Object>();
		StringBuffer query = new StringBuffer();
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		DateFormat format = sdf;
		try {

			query.append("select * from extintor e ");
			if (this.getResponsable() != null
					&& !this.getResponsable().isEmpty()) {
				query.append("where e.fk_usuario = " + this.getResponsable());
			}

			listaExtintores = this.getServicioExtintor().getExtintores();
			List<ExtintorTo> temp = new ArrayList<ExtintorTo>();
			for (ExtintorTo e : listaExtintores) {
				if (e.getHabilitado() != 0) {
					e.setAlerta(DateUtil.getDateDiff(1,
							e.getUltimoMantenimiento(), new Date()) > 11 ? true
							: false);
					e.setUltimoMantenimiento(format.parse(sdf.format(e
							.getUltimoMantenimiento())));
					e.setProximoMantenimiento(format.parse(sdf.format(e
							.getProximoMantenimiento())));
					temp.add(e);

				}
				listaExtintores = new ArrayList<ExtintorTo>();
				listaExtintores = temp;
			}
			parameters.put("REPORT_NAME", "GeneralExtintores");
			parameters.put("REPORT_TITLE", "Reporte General de Extintores");
			parameters.put("LISTA_DATOS_REPORTES", listaExtintores);
			tipoReporte = "pdf";

		} catch (Exception e) {
			logger.error("Ha ocurrido un error inesperado " + e);
		}
		return this.generarReporte();
	}

	public String generarReportePorRangoDeFechas() {
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		parameters = new HashMap<String, Object>();
		List<Object> objects = new ArrayList<Object>();

		try {
			ExtintorTo e;
			List<ExtintorTo> extintores = new ArrayList<ExtintorTo>();
			if (this.getInicioProximoMantenimiento() != null
					&& this.getFinProximoMantenimiento() != null) {
				objects = this.getServicioReporte().getExtintoresPorFecha(
						sdf.format(inicioProximoMantenimiento),
						sdf.format(finProximoMantenimiento));
			} else if (this.getInicioUltimoMantenimiento() != null
					&& this.getFinUltimoMantenimiento() != null) {
				objects = this.getServicioReporte().getExtintoresPorFecha(
						sdf.format(inicioUltimoMantenimiento),
						sdf.format(finUltimoMantenimiento));
			}

			for (Object obj : objects) {
				e = new ExtintorTo();
				Object[] array = (Object[]) obj;
				e = this.getServicioExtintor().getExtintor(
						((BigInteger) array[0]).longValue());
				extintores.add(e);
			}
			parameters.put("REPORT_NAME", "GeneralExtintores");
			parameters.put("REPORT_TITLE", "Reporte General de Extintores");
			parameters.put("LISTA_DATOS_REPORTES", extintores);
			tipoReporte = "pdf";
		} catch (Exception e) {
			logger.error("Ha ocurrido un error inesperado " + e);
		}

		return this.generarReporte();
	}

	private void obtenerContents() {
		if (tipoReporte.equalsIgnoreCase("pdf")) {
			tipoDocumento = TipoDocumento.PDF;
			setContentType("application/pdf");
			extensionReporte = ".pdf";
		} else if (tipoReporte.equalsIgnoreCase("xls")) {
			tipoDocumento = TipoDocumento.EXCEL;
			setContentType("application/vnd.ms-excel");
			extensionReporte = ".xls";
		} else if (tipoReporte.equalsIgnoreCase("html")) {
			tipoDocumento = TipoDocumento.HTML;
			setContentType("text/html");
			extensionReporte = ".htm";
		}
	}

	public String getContentType() {
		return contentType;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String getTipoReporte() {
		return tipoReporte;
	}

	public void setTipoReporte(String tipoReporte) {
		this.tipoReporte = tipoReporte;
	}

	public String getExtensionReporte() {
		return extensionReporte;
	}

	public void setExtensionReporte(String extensionReporte) {
		this.extensionReporte = extensionReporte;
	}

	public InputStream getInputStream() {
		return inputStream;
	}

	public void setInputStream(InputStream inputStream) {
		this.inputStream = inputStream;
	}

	public HashMap<String, Object> getParameters() {
		return parameters;
	}

	public void setParameters(HashMap<String, Object> parameters) {
		this.parameters = parameters;
	}

	public TipoOrientacion getTipoOrientacion() {
		return tipoOrientacion;
	}

	public void setTipoOrientacion(TipoOrientacion tipoOrientacion) {
		this.tipoOrientacion = tipoOrientacion;
	}

	public TipoDocumento getTipoDocumento() {
		return tipoDocumento;
	}

	public void setTipoDocumento(TipoDocumento tipoDocumento) {
		this.tipoDocumento = tipoDocumento;
	}

	public List<ExtintorTo> getListaExtintores() {
		return listaExtintores;
	}

	public void setListaExtintores(List<ExtintorTo> listaExtintores) {
		this.listaExtintores = listaExtintores;
	}

	public List<String> getCodes() {
		return codes;
	}

	public void setCodes(List<String> codes) {
		this.codes = codes;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public ExtintorTo getExtintor() {
		return extintor;
	}

	public void setExtintor(ExtintorTo extintor) {
		this.extintor = extintor;
	}

	public String getResponsable() {
		return responsable;
	}

	public void setResponsable(String responsable) {
		this.responsable = responsable;
	}

	public Date getFinUltimoMantenimiento() {
		return finUltimoMantenimiento;
	}

	public void setFinUltimoMantenimiento(Date finUltimoMantenimiento) {
		this.finUltimoMantenimiento = finUltimoMantenimiento;
	}

	public Date getInicioUltimoMantenimiento() {
		return inicioUltimoMantenimiento;
	}

	public void setInicioUltimoMantenimiento(Date inicioUltimoMantenimiento) {
		this.inicioUltimoMantenimiento = inicioUltimoMantenimiento;
	}

	public Date getFinProximoMantenimiento() {
		return finProximoMantenimiento;
	}

	public void setFinProximoMantenimiento(Date finProximoMantenimiento) {
		this.finProximoMantenimiento = finProximoMantenimiento;
	}

	public Date getInicioProximoMantenimiento() {
		return inicioProximoMantenimiento;
	}

	public void setInicioProximoMantenimiento(Date inicioProximoMantenimiento) {
		this.inicioProximoMantenimiento = inicioProximoMantenimiento;
	}
}
